跳到主要内容

Docker Compose Network 配置笔记

是的,即使两个服务不写在同一个 Docker Compose 配置文件中,也可以实现隔离。这种情况下,可以通过 自定义网络 来实现服务之间的隔离或互通。

以下是如何在两个独立的 Docker Compose 配置文件中实现隔离的详细说明:


方法 1:完全隔离(不同网络)

如果两个服务完全独立,且不需要互相通信,可以将它们放在不同的 Docker 网络中:

配置文件 1 (docker-compose-service1.yml)

version: '3.9'

services:
app_service1:
image: my_app_service1_image # 替换为第一个服务的镜像
networks:
- network_service1
environment:
DATABASE_HOST: postgres_service1
DATABASE_PORT: 5432
DATABASE_USER: user1
DATABASE_PASSWORD: password1
DATABASE_NAME: db1

postgres_service1:
image: postgres:latest
container_name: postgres_service1
networks:
- network_service1
environment:
POSTGRES_USER: user1
POSTGRES_PASSWORD: password1
POSTGRES_DB: db1
ports:
- "5432:5432" # 可选:仅在需要从宿主机访问时映射端口

networks:
network_service1:
driver: bridge

配置文件 2 (docker-compose-service2.yml)

version: '3.9'

services:
app_service2:
image: my_app_service2_image # 替换为第二个服务的镜像
networks:
- network_service2
environment:
DATABASE_HOST: postgres_service2
DATABASE_PORT: 5432
DATABASE_USER: user2
DATABASE_PASSWORD: password2
DATABASE_NAME: db2

postgres_service2:
image: postgres:latest
container_name: postgres_service2
networks:
- network_service2
environment:
POSTGRES_USER: user2
POSTGRES_PASSWORD: password2
POSTGRES_DB: db2
ports:
- "5433:5432" # 可选:仅在需要从宿主机访问时映射端口

networks:
network_service2:
driver: bridge

启动服务

分别在两个配置文件所在的目录运行以下命令:

docker-compose -f docker-compose-service1.yml up -d
docker-compose -f docker-compose-service2.yml up -d

效果

  • 两个服务被放在不同的网络中,完全隔离,无法直接通信。
  • 如果需要从宿主机访问 PostgreSQL,可以通过 5432 访问 postgres_service1,通过 5433 访问 postgres_service2

方法 2:部分隔离(共享网络)

如果两个服务需要部分隔离,但仍需要通过网络通信,可以让它们共享一个 自定义网络

创建共享网络

首先,创建一个共享网络:

docker network create shared_network

配置文件 1 (docker-compose-service1.yml)

version: '3.9'

services:
app_service1:
image: my_app_service1_image
networks:
- shared_network
environment:
DATABASE_HOST: postgres_service1
DATABASE_PORT: 5432
DATABASE_USER: user1
DATABASE_PASSWORD: password1
DATABASE_NAME: db1

postgres_service1:
image: postgres:latest
container_name: postgres_service1
networks:
- shared_network
environment:
POSTGRES_USER: user1
POSTGRES_PASSWORD: password1
POSTGRES_DB: db1
ports:
- "5432:5432"

networks:
shared_network:
external: true

配置文件 2 (docker-compose-service2.yml)

version: '3.9'

services:
app_service2:
image: my_app_service2_image
networks:
- shared_network
environment:
DATABASE_HOST: postgres_service2
DATABASE_PORT: 5432
DATABASE_USER: user2
DATABASE_PASSWORD: password2
DATABASE_NAME: db2

postgres_service2:
image: postgres:latest
container_name: postgres_service2
networks:
- shared_network
environment:
POSTGRES_USER: user2
POSTGRES_PASSWORD: password2
POSTGRES_DB: db2
ports:
- "5433:5432"

networks:
shared_network:
external: true

启动服务

分别在两个配置文件所在的目录运行以下命令:

docker-compose -f docker-compose-service1.yml up -d
docker-compose -f docker-compose-service2.yml up -d

效果

  • 两个服务共享同一个网络 shared_network,可以通过容器名(如 postgres_service1postgres_service2)相互通信。
  • 宿主机仍然可以通过 54325433 访问两个 PostgreSQL 实例。

方法 3:动态网络(无需预先创建网络)

如果不想手动创建网络,可以在两个配置文件中定义相同名称的网络,Docker Compose 会自动将它们加入同一个网络。

配置文件 1 (docker-compose-service1.yml)

version: '3.9'

services:
app_service1:
image: my_app_service1_image
networks:
- common_network
environment:
DATABASE_HOST: postgres_service1
DATABASE_PORT: 5432
DATABASE_USER: user1
DATABASE_PASSWORD: password1
DATABASE_NAME: db1

postgres_service1:
image: postgres:latest
container_name: postgres_service1
networks:
- common_network
environment:
POSTGRES_USER: user1
POSTGRES_PASSWORD: password1
POSTGRES_DB: db1
ports:
- "5432:5432"

networks:
common_network:
name: shared_network
driver: bridge

配置文件 2 (docker-compose-service2.yml)

version: '3.9'

services:
app_service2:
image: my_app_service2_image
networks:
- common_network
environment:
DATABASE_HOST: postgres_service2
DATABASE_PORT: 5432
DATABASE_USER: user2
DATABASE_PASSWORD: password2
DATABASE_NAME: db2

postgres_service2:
image: postgres:latest
container_name: postgres_service2
networks:
- common_network
environment:
POSTGRES_USER: user2
POSTGRES_PASSWORD: password2
POSTGRES_DB: db2
ports:
- "5433:5432"

networks:
common_network:
name: shared_network
driver: bridge

启动服务

分别在两个配置文件所在的目录运行以下命令:

docker-compose -f docker-compose-service1.yml up -d
docker-compose -f docker-compose-service2.yml up -d

效果

  • 两个服务共享网络 shared_network,可以通过容器名相互通信。
  • Docker Compose 会自动创建 shared_network,无需手动创建。

这段代码是 Docker Compose 文件中定义网络的部分,涉及到两个自定义网络的配置:docker-internalinternet。以下是对这段代码的详细说明:


代码结构

networks:
docker-internal:
driver: bridge
internal: true
internet:
driver: bridge

详细解释

1. networks

  • networks 是 Docker Compose 文件中定义自定义网络的顶级关键字。
  • 它允许为服务创建和配置专属的网络,以便服务之间可以通信,同时可以控制是否允许访问外部网络(如互联网)。

2. docker-internal

docker-internal:
driver: bridge
internal: true
  • driver: bridge:

    • 指定网络使用的是 Docker 的 桥接网络(bridge network) 模式。
    • 这是 Docker 的默认网络驱动类型,适合在单个宿主机上运行的容器之间通信。
    • 每个桥接网络是独立的,容器只能与同一个网络中的其他容器通信。
  • internal: true:

    • 这是一个关键配置,表示该网络是 内部网络
    • 内部网络的特点是 禁止容器访问宿主机网络和外部互联网
    • 任何连接到该网络的容器只能与同一网络中的其他容器通信,无法访问外部网络(例如,无法连接到互联网或宿主机的其他服务)。
    • 适合用于隔离敏感的服务,例如数据库、缓存服务等,确保这些服务只能被内部的应用程序访问,而不会暴露给外界。
应用场景
  • 将数据库服务(例如 PostgreSQL、MySQL 等)放置在 docker-internal 网络中,确保数据库服务无法直接访问互联网,避免安全风险。
  • 例如:
    • 数据库服务连接到 docker-internal
    • 应用服务同时连接到 docker-internal 和其他网络(如 internet),从而实现对数据库的访问。

3. internet

internet:
driver: bridge
  • driver: bridge:
    • 同样使用桥接网络模式。
    • 这是一个普通的桥接网络,没有设置 internal: true,因此默认允许容器访问宿主机网络和互联网。
应用场景
  • 将需要访问互联网的服务(例如应用服务、API 网关等)放置在 internet 网络中。
  • 适用于需要访问外部资源(如第三方 API、远程服务器)的服务。

如何使用这些网络

在 Docker Compose 文件中定义了网络后,可以通过 networks 配置将服务加入到对应的网络。例如:

version: '3.9'

services:
app:
image: my_app_image
networks:
- docker-internal # 应用程序可以访问数据库
- internet # 应用程序也可以访问互联网
depends_on:
- db

db:
image: postgres:latest
networks:
- docker-internal # 数据库只能被内部服务访问
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: example_db

networks:
docker-internal:
driver: bridge
internal: true
internet:
driver: bridge

示例说明

服务通信

  • db 服务(数据库)连接到 docker-internal 网络,因此它无法访问互联网,也无法直接与 internet 网络中的其他容器通信。
  • app 服务连接到两个网络:
    • 通过 docker-internal 网络可以访问 db 服务。
    • 通过 internet 网络可以访问互联网。

网络隔离的好处

  • 数据库服务(db)不会暴露给外部网络,提升了安全性。
  • 应用服务(app)可以同时访问数据库和互联网,满足业务需求。

总结

  • docker-internal 网络

    • 使用 internal: true 禁止网络访问外部互联网。
    • 适用于需要隔离的服务,例如数据库、缓存服务等。
  • internet 网络

    • 普通桥接网络,允许容器访问互联网。
    • 适用于需要对外通信的服务,例如应用服务、API 服务等。

通过这种方式,可以灵活地控制容器的网络访问权限,确保服务的隔离性和安全性,同时满足业务需求。